﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ApplLogic.ApplClasses;
using ConnectionObjects;
using TCPClient.RequestsToServerHandlers;

namespace TCPClient.UI.LogicForUserControls
{
    public class ScMainUserControlLogicManager : ScMainUserControlLogicBase
    {
        private static ScMainUserControlLogicManager m_Instance = null;

        public static void Create(RequestsToServerHandler handler)
        {
            if (m_Instance == null)
            {
                m_Instance = new ScMainUserControlLogicManager(handler);
            }
        }

        public static ScMainUserControlLogicManager Instance
        {
            get { return m_Instance; }
        }

        private  ScMainUserControlLogicManager(RequestsToServerHandler handler)
            :base(handler)
        {
            
        }

        public ApplShift ShowShiftDetails(DateTime startTime, DateTime endTime)
        {
            return downCast().ShowShiftDetails(startTime, endTime).RetVal as ApplShift;
        }

        private RequestsToServerHandlerForManager downCast()
        {
            return m_HandlerBase as RequestsToServerHandlerForManager;
        }

        public List<ApplShift> GetAllWantedShifts(string workerId)
        {
            OutConnectionObject result = downCast().GetAllShiftsThatWorkerAskedWithType(
                workerId, eType.WANTED, m_StartTimeOfCurrentWeek.AddDays(7).AddHours(-1), m_EndTimeOfCurrentWeek.AddDays(7).AddHours(1));
            return result.RetVal as List<ApplShift>;
        }

        public List<ApplShift> GetAllForbiddenShifts(string workerId)
        {
            OutConnectionObject result = downCast().GetAllShiftsThatWorkerAskedWithType(
                workerId, eType.FORBIDDEN, m_StartTimeOfCurrentWeek.AddDays(7).AddHours(-1), m_EndTimeOfCurrentWeek.AddDays(7).AddHours(1));
            return result.RetVal as List<ApplShift>;
        }

        public string GetDefaultPeriodBetweenShiftsForRunningAlgo()
        {
            return downCast().GetDefaultPeriodBetweenShiftsForRunningAlgo().RetVal as string;
        }

        public string GetMinNumberOfShiftsPerDay()
        {
            return downCast().GetMinNumberOfShiftsPerDay().RetVal as string;
        }

        public void ChangeDefaultPeriodBetweenShiftsForRunningAlgo(string newPeriod)
        {
            downCast().ChangeDefaultPeriodBetweenShiftsForRunningAlgo(newPeriod);
        }

        public Dictionary<ApplShift, List<ApplSingleResult>> GetAllResultsOfAllShiftsOfWorker(string workerId)
        {
            return
                downCast().GetAllResultsOfAllShiftsOfWorker(m_StartTimeOfTheWeek.AddHours(-1),
                                                            m_EndTimeOfTheWeek.AddHours(1), workerId).RetVal as
                Dictionary<ApplShift, List<ApplSingleResult>>;
        }

        public void NotifyAllWorkersForNewShiftCreation(string additionalInfo)
        {
            downCast().NotifyAllWorkersForNewShiftCreation(m_StartTimeOfCurrentWeek.AddDays(7).AddHours(-1),
                                                           m_EndTimeOfCurrentWeek.AddDays(7).AddHours(1), additionalInfo);
        }

        public void NotifyWorkersThatnNotSendRequests(string additionalInfo)
        {
            downCast().NotifyWorkersThatnNotSendRequests(m_StartTimeOfCurrentWeek.AddDays(7).AddHours(-1),
                                                           m_EndTimeOfCurrentWeek.AddDays(7).AddHours(1), additionalInfo);
        }

        public Dictionary<ApplShift, List<ApplSingleRequest>> GetAllRequestsOfAllShiftsOfWorker(string workerId)
        {
            return
                downCast().GetAllRequestsOfAllShiftsOfWorker(m_StartTimeOfTheWeek.AddHours(-1),
                                                m_EndTimeOfTheWeek.AddHours(1), workerId).RetVal as
                 Dictionary<ApplShift, List<ApplSingleRequest>>;
        }

        public void UpdateServerWithWorkerRequest(List<ShiftRequestFromGUI> requests, ApplWorker worker)
        {
            List<ApplSingleRequest> workerRequest = convertTheUiRequestToApplRequest(requests, worker);
            sendAllNewRequestsToServer(workerRequest, worker);
        }

        private void sendAllNewRequestsToServer(List<ApplSingleRequest> workerRequest, ApplWorker worker)
        {
            downCast().RenterAllRequestsOfWorker(worker.PersonalDetails.Id, m_StartTimeOfCurrentWeek.AddDays(7).AddHours(-1),
                                                 m_EndTimeOfTheWeek.AddDays(7).AddHours(1),
                                                 workerRequest);
        }

        private List<ApplSingleRequest> convertTheUiRequestToApplRequest(List<ShiftRequestFromGUI> requests, ApplWorker worker)
        {
            List<ApplSingleRequest> workerRequest = new List<ApplSingleRequest>();
            foreach (var shiftRequestFromGui in requests)
            {
                ApplSingleRequest request = new ApplSingleRequest();
                request.ApplWorker = worker;
                request.ApplShift = downCast().ShowShiftDetails(shiftRequestFromGui.StartDate,
                                                                            shiftRequestFromGui.EndDate).RetVal as ApplShift;
                request.Type = shiftRequestFromGui.Type;
                workerRequest.Add(request);
            }
            return workerRequest;
        }

        public List<ApplWorker> GetAllWorkers()
        {
            return downCast().GetAllWorkers().RetVal as List<ApplWorker>;
        }

        public string GetNumnerOfWorkersInShift()
        {
            return downCast().GetNumberOfWorkersPerShift().RetVal as string;
        }

        public void ChangeStartTimeOfWork(string startTimeOfWork)
        {
            downCast().ChangeStartTimeOfWork(startTimeOfWork);
        }

        public void ChangeNumberOfShiftsPerDay(string numberOfShift)
        {
            downCast().ChangeNumberOfShiftsPerDay(numberOfShift);
        }

        public void ChangeLenghtOfShift(string lenght)
        {
            downCast().ChangeLenghtOfShift(lenght);
        }

        public void ChangeNumnerOfWorkersInShift(string numOfWorkers)
        {
            downCast().ChangeNumberOfWorkersPerShift(numOfWorkers);
        }

        public void AddResultShiftToWorker(string workerId, DateTime startTime, DateTime endTime)
        {
            downCast().AddResultShiftToWorker(workerId, startTime, endTime);
        }

        public void DeleteResult(string workerId, DateTime startTime, DateTime endTime)
        {
            downCast().DeleteResult(workerId, startTime, endTime);
        }

        public string ChangeResultRegistrationOfAworker(string workerId, DateTime startTimeToremove, DateTime endTimeToRemove,
                DateTime startTimeToAdd, DateTime endTimeToAdd)
        {
            string message = string.Empty;
            OutConnectionObject result =
                downCast().ChangeResultRegistrationOfAworker(workerId, startTimeToremove, endTimeToRemove,
                startTimeToAdd, endTimeToAdd);
            return message = result.IsErrorOccured() ? result.ExceptionMessage : "Ok";
        }

        public string IsWorkerGotShift(string workerId, DateTime startTime, DateTime endTime)
        {
            OutConnectionObject result =
                downCast().IsWorkerGotShift(workerId, startTime, endTime);
            return result.RetVal as string;
        }

        public List<ApplWorker> GetAllWorkersThatNotAskedForanyShiftInRange()
        {
            caclulateStartAndEndTimeOfTheWeek(DateTime.Today, out m_StartTimeOfCurrentWeek, out m_EndTimeOfCurrentWeek);
            OutConnectionObject result =
                downCast().GetAllWorkersThatNotAskedForanyShiftInRange(m_StartTimeOfCurrentWeek.AddDays(7).AddHours(-1), 
                m_EndTimeOfCurrentWeek.AddDays(7).AddHours(1));
            return result.RetVal as List<ApplWorker>;
        }

        public List<ApplWorker> GetAllWorkersThatAskedForShiftsInRange()
        {
            caclulateStartAndEndTimeOfTheWeek(DateTime.Today, out m_StartTimeOfCurrentWeek, out m_EndTimeOfCurrentWeek);
            OutConnectionObject result = downCast().GetAllWorkersThatAskedForShiftsInRange(m_StartTimeOfCurrentWeek.AddDays(7).AddHours(-1),
                m_EndTimeOfCurrentWeek.AddDays(7).AddHours(1));
            return result.RetVal as List<ApplWorker>;
        }

        public List<ApplWorker> GetAllWorkersThatAskedForAShiftWithType(string shiftId, eType type, DateTime startTime, DateTime endTime)
        {
            return downCast().GetAllWorkersThatAskedForAShiftWithType(shiftId, type, startTime, endTime).RetVal as List<ApplWorker>;
        }

        public void UpdateShift(ApplShift updatedShift)
        {
            downCast().UpdateShift(updatedShift);
        }

        public List<ApplWorker> GetAllWorkersThatGotShiftInStep(string shiftId, eResult result, DateTime startTime, DateTime endTime)
        {
            return downCast().GetAllWorkersThatGotShiftInStep(shiftId, result, startTime, endTime).RetVal as List<ApplWorker>;
        }

        public Dictionary<ApplShift, List<ApplWorker>> GetAllRequestsOfAllShiftsAsWanted()
        {
            OutConnectionObject result = downCast().GetAllRequestsOfAllShiftsWithType(eType.WANTED, m_StartTimeOfTheWeek.AddHours(-1), m_EndTimeOfTheWeek.AddHours(1));
            return result.RetVal as Dictionary<ApplShift, List<ApplWorker>>;
        }

        public Dictionary<ApplShift, List<ApplWorker>> GetAllRequestsOfAllShiftsAsForbidden()
        {
            OutConnectionObject result = downCast().GetAllRequestsOfAllShiftsWithType(eType.FORBIDDEN, m_StartTimeOfTheWeek.AddHours(-1), m_EndTimeOfTheWeek.AddHours(1));
            return result.RetVal as Dictionary<ApplShift, List<ApplWorker>>;
        }

        public Dictionary<ApplShift, List<ApplWorker>> GetAllResultsOfAllShiftsAsFirst()
        {
            OutConnectionObject result = downCast().GetAllResultsOfAllShiftsWithResult(eResult.FIRST, m_StartTimeOfTheWeek, m_EndTimeOfTheWeek);
            return result.RetVal as Dictionary<ApplShift, List<ApplWorker>>;
        }

        public Dictionary<ApplShift, List<ApplWorker>> GetAllResultsOfAllShiftsAsSecond()
        {
            OutConnectionObject result = downCast().GetAllResultsOfAllShiftsWithResult(eResult.SECOND, m_StartTimeOfTheWeek, m_EndTimeOfTheWeek);
            return result.RetVal as Dictionary<ApplShift, List<ApplWorker>>;
        }

        public Dictionary<ApplShift, List<ApplWorker>> GetAllResultsOfAllShiftsAsThird()
        {
            OutConnectionObject result = downCast().GetAllResultsOfAllShiftsWithResult(eResult.THIRD, m_StartTimeOfTheWeek, m_EndTimeOfTheWeek);
            return result.RetVal as Dictionary<ApplShift, List<ApplWorker>>;
        }

        public Dictionary<ApplShift, List<ApplSingleRequest>> GetAllRequestsOfAllShifts()
        {
            OutConnectionObject result =
                downCast().GetAllRequestsOfAllShifts(m_StartTimeOfTheWeek.AddHours(-1),
                                                     m_EndTimeOfTheWeek.AddHours(1));
            return result.RetVal as Dictionary<ApplShift, List<ApplSingleRequest>>;
        }

        public Dictionary<ApplShift, List<ApplSingleResult>> GetAllResultsfAllShifts()
        {
            OutConnectionObject result =
                downCast().GetAllResultsOfAllShifts(m_StartTimeOfTheWeek.AddHours(-1),
                                                     m_EndTimeOfTheWeek.AddHours(1));
            return result.RetVal as Dictionary<ApplShift, List<ApplSingleResult>>;
        }

        public Dictionary<ApplShift, List<ApplSingleResult>> GetResultsOfSpecificShift(DateTime start, DateTime end)
        {
            OutConnectionObject result =
                    downCast().GetAllResultsOfAllShifts(start, end);
            return result.RetVal as Dictionary<ApplShift, List<ApplSingleResult>>;
        }

        public List<ApplShift> GetAllRequestedShifsOfWorker(string workerId)
        {
            OutConnectionObject result = downCast().GetAllShiftsThatWorkerAsked(workerId,
                m_StartTimeOfTheWeek.AddHours(-1), m_EndTimeOfTheWeek.AddHours(1));
            return result.RetVal as List<ApplShift>;
        }

        public List<ApplShift> GetAllRegisteredShifsOfWorker(string workerId)
        {
            OutConnectionObject result = downCast().GetAllShiftsThatWorkerIsRegisteredTo(workerId,
                m_StartTimeOfTheWeek.AddHours(-1), m_EndTimeOfTheWeek.AddHours(1));
            return result.RetVal as List<ApplShift>;
        }

        public List<ApplShift> GetAllRegisteredShifsOfWorkerWithType(string workerId, eResult resultStep)
        {
            OutConnectionObject result = downCast().GetAllShiftsThatWorkerIsRegisteredToInStep(workerId,
                resultStep, m_StartTimeOfTheWeek.AddHours(-1), m_EndTimeOfTheWeek.AddHours(1));
            return result.RetVal as List<ApplShift>;
        }

        public List<ApplShift> GetAllRequestedShiftsOfWorkerWithType(string workerId, eType type)
        {
            OutConnectionObject result = downCast().GetAllShiftsThatWorkerAskedWithType(
                workerId, type, m_StartTimeOfTheWeek.AddHours(-1), m_EndTimeOfTheWeek.AddHours(1));
            return result.RetVal as List<ApplShift>;
        }

        public void RunAlgo()
        {
            caclulateStartAndEndTimeOfTheWeek(DateTime.Today, out m_StartTimeOfCurrentWeek, out m_EndTimeOfCurrentWeek);
            OutConnectionObject result = downCast().RunAlgo(m_StartTimeOfCurrentWeek.AddDays(7).AddHours(-1),
                m_EndTimeOfCurrentWeek.AddDays(7).AddHours(1));
        }

    }
}
